/**
 *******************************************************************************
 * \brief   CAS EBX Project Work "Kaffeemaschine"
 *
 * \file    device.c
 * \version 1.0
 * \date    18.08.2010
 * \author  Liechti Beat
 *
 * \remark  Last Modifications:
 * \remark  V1.0, 18.08.2010   Initial release
 *******************************************************************************
 **/

/*
 *******************************************************************************
 * Imports
 *******************************************************************************
 */

#include <errno.h>
#include <fcntl.h>		/* For O_* constants */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>	/* For mode constants */
#include <unistd.h>
#include <syslog.h>

#include "device.h"

/*
 *******************************************************************************
 * Definitions
 *******************************************************************************
 */

/*
 *******************************************************************************
 * Local Function Declaration
 *******************************************************************************
 */


/*
 *******************************************************************************
 * Global Function Definition
 *******************************************************************************
 */

/**
 *******************************************************************************
 * openDeviceRead
 *
 * \brief opens a device for reading
 *
 * \param path The path of the device
 *
 * \return tDevice* Pointer to device ADT structure, NULL if error
 *
 *******************************************************************************
 **/
tDevice *openDeviceRead(char *path)
{
	// create device
	tDevice *device = malloc(sizeof(tDevice));
	if (device != NULL)
	{
		memset(device, 0, sizeof(tDevice));
		device->path = strdup(path);
		device->fd = open(device->path, O_RDONLY);
		if (device->fd < 0)
		{
			perror("could not open device");
			free(device->path);
			free(device);
			device = NULL;
		}
	}
	return device;
}

/**
 *******************************************************************************
 * openDeviceWrite
 *
 * \brief opens a device for writing
 *
 * \param path The path of the device
 *
 * \return tDevice* Pointer to device ADT structure, NULL if error
 *
 *******************************************************************************
 **/
tDevice *openDeviceWrite(char *path)
{
	// create device
	tDevice *device = malloc(sizeof(tDevice));
	if (device != NULL)
	{
		memset(device, 0, sizeof(tDevice));
		device->path = strdup(path);
		device->fd = open(device->path, O_WRONLY);
		if (device->fd < 0)
		{
			perror("could not open device");
			free(device->path);
			free(device);
			device = NULL;
		}
	}
	return device;
}

/**
 *******************************************************************************
 * closeDevice
 *
 * \brief closes the device, resources are deallocated.
 *
 * \param device Pointer to device ADT structure
 *
 *
 *******************************************************************************
 **/
void closeDevice(tDevice *device)
{
	if (device != NULL)
	{
		if (device->fd >= 0)
		{
			close(device->fd);
			device->fd = -1;
		}
		if (device->path != NULL)
		{
			free(device->path);
			device->path = NULL;
		}
		free(device);
	}
}

/**
 *******************************************************************************
 * readDevice
 *
 * \brief reads out an int from a device.
 *
 * \param device Pointer to device ADT structure
 * \param val_p Pointer to destination for data
 *
 * \return bytes read = sizeof(int), error if < 0
 *
 *******************************************************************************
 **/
int readDevice(tDevice *device, int *val_p)
{
	int ret = EFAULT;
	if (device != NULL)
	{
		if (device->fd >= 0)
		{
			ssize_t size = read(device->fd, val_p, sizeof(*val_p));
			if (size == sizeof(*val_p))
			{
				ret = sizeof(*val_p);
			}
		}
	}
	return ret;
}

/**
 *******************************************************************************
 * writeDevice
 *
 * \brief writes an int to a device.
 *
 * \param device Pointer to device ADT structure
 * \param val Value to be written
 *
 * \return bytes read = sizeof(int), error if < 0
 *
 *******************************************************************************
 **/
int writeDevice(tDevice *device, int val)
{
	int ret = EFAULT;
	if (device != NULL)
	{
		if (device->fd >= 0)
		{
			ssize_t size = write(device->fd, &val, sizeof(val));
			if (size == sizeof(val))
			{
				ret = sizeof(val);
			}
		}
	}
	return ret;
}

